package com.thornbird.vehiclerecycling.config;

import com.thornbird.vehiclerecycling.service.OAuth2Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@EnableWebSecurity
public class OAuth2LoginConfig {

    public static final String GLOBAL_SESSIONS = "globalSessions";

    public static final String CURRENT_USER = "currentUser";

    @Autowired
    private OAuth2Service oAuth2Service;

    @Configuration
    @Order(SecurityProperties.BASIC_AUTH_ORDER)
    public class OAuth2LoginConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .csrf().disable()
                    .authorizeRequests()
                    .antMatchers("/error/**", "/login/**",
                            "/api/ping", "/api/currentUser", "/page/public/**",
                            "/css/**", "/fonts/**", "/images/**", "/js/**", "/libs/**", "/favicon.png"
                    ).permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .oauth2Login()
                    .successHandler(new ApplicationAuthenticationSuccessHandler())
                    .loginPage("/login/oauth2")
                    .authorizationEndpoint()
                    .baseUri("/login/oauth2/authorization")
                    .and().and()
                    .logout()
                    .deleteCookies()
                    .clearAuthentication(true)
                    .invalidateHttpSession(true)
                    .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                    .logoutSuccessHandler(new ApplicationLogoutSuccessHandler("/login/oauth2/exit"));
        }
    }


    class ApplicationLogoutSuccessHandler implements LogoutSuccessHandler {

        private String oauth2LogoutUri;

        public ApplicationLogoutSuccessHandler(String oauth2LogoutUri) {
            this.oauth2LogoutUri = oauth2LogoutUri;
        }

        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                    Authentication authentication) throws IOException, ServletException {
            HttpSession session = request.getSession();
            if (session.getAttribute(CURRENT_USER) != null) {
                session.setAttribute(CURRENT_USER, null);
            }
            if (oauth2LogoutUri != null && !oauth2LogoutUri.isEmpty()) {
                response.sendRedirect(oauth2LogoutUri);
            } else {
                response.sendRedirect("/");
            }
        }

    }


    class ApplicationAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                            Authentication authentication) throws IOException, ServletException {
            HttpSession session = request.getSession();
            if (session.getAttribute(CURRENT_USER) == null) {
                session.setAttribute(CURRENT_USER, oAuth2Service.saveUser(authentication));
            }
            SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
            if (savedRequest != null) {
                response.sendRedirect(savedRequest.getRedirectUrl());
            } else {
                response.sendRedirect("/");
            }
        }

    }

}

